

namespace NodeBasedSkillEditor.Model.Node.RT
{
    public class Node_Foreach_RT : RT_Node
    {
        public RT_FlowPort FlowIn_RT;

        public RT_ValueListPort ValueList_RT;

        public RT_FlowPort Loop_RT;

        public RT_SingleValuePort ValueMember_RT;

        public RT_FlowPort AfterLoop_RT;

        public Node_Foreach_RT(Node_Foreach sourceData, RT_DAG parentDag) : base(sourceData, parentDag)
        {
            FlowIn_RT = new RT_FlowPort(EPortIOType.Input, sourceData.FlowIn, this);

            ValueList_RT = new RT_ValueListPort(EPortIOType.Input, sourceData.ValueList, this);

            Loop_RT = new RT_FlowPort(EPortIOType.Output, sourceData.Loop, this);

            ValueMember_RT = new RT_SingleValuePort(EPortIOType.Output, sourceData.ValueMember, this);
            ValueMember_RT.OnGetValue = GetValueMember;

            AfterLoop_RT = new RT_FlowPort(EPortIOType.Output, sourceData.AfterLoop, this);
        }

        public AValue GetValueMember(DAG_Executor executor)
        {
            ValueMember_RT.SourceValue.Reset();
            var info = executor.GetExeInfoOfNode(this) as Foreach_Info;
            var list = ValueList_RT.GetValueList(executor);

            if (info != null && list != null)
            {
                var index = info.CurrentIndex;
                if (index >= 0 && index < list.Count)
                {
                    var currValue = list[index];
                    ValueMember_RT.SourceValue.Assign(currValue);
                }
            }
            return ValueMember_RT.SourceValue;
        }

        public override (EDagExeState, RT_Node) ForewardExecute(DAG_Executor executor)
        {
            var list = ValueList_RT.GetValueList(executor);
            if (list != null && list.Count > 0)
            {
                var info = new Foreach_Info();
                executor.SetExeInfoOfNode(this, info);
                return TryForewardByPort(Loop_RT);
            }
            else
            {
                return TryForewardByPort(AfterLoop_RT);
            }
        }

        public override (EDagExeState, RT_Node) BackwardExecute(DAG_Executor executor)
        {
            var info = executor.GetExeInfoOfNode(this) as Foreach_Info;
            var list = ValueList_RT.GetValueList(executor);
            if (info != null && list != null)
            {
                info.CurrentIndex++;
                int currIndex = info.CurrentIndex;
                if (currIndex >= 0 && currIndex < list.Count)
                {
                    return TryForewardByPort(Loop_RT);
                }
                else if (currIndex == list.Count)
                {
                    return TryForewardByPort(AfterLoop_RT);
                }
            }
            return (EDagExeState.Backward, null);
        }
    }

    public class Foreach_Info : RT_NodeExeInfo
    {
        public int CurrentIndex = 0;
    }
}